package basicdata

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"sync"
	"time"

	jsoniter "github.com/json-iterator/go"
	"github.com/pkg/errors"
	"gpt-api/framework/codes"
	"gpt-api/framework/log"
)

const (
	pageCount       = 1000
	matchTotalCount = 50
)

type BasicData struct {
	languageLastUpdate time.Time
	EnuslanguageMap    sync.Map
	ZhcnlanguageMap    sync.Map
}

func New() *BasicData {
	return &BasicData{}
}

func (d *BasicData) Start() {
	//d.fatalError(d.syncLanguage(time.Millisecond))

	//d.backgroundRun(time.Minute, 600*time.Second, d.syncLanguage)
}

func (d *BasicData) syncLanguage(duration time.Duration) error {
	languages := []string{"ar", "en-US", "es", "id", "ja", "ko", "ms", "pt", "th", "vi", "zh-CN"}
	type LanguageData map[string]map[string]string

	var respData struct {
		Code int          `json:"code"`
		Data LanguageData `json:"data"`
	}

	url := "http://language.siling-tech.com/api/v1/language/translation"
	httpClient := http.Client{Timeout: time.Minute * 2}
	param := map[string]interface{}{}
	param["project_id"] = 3
	marshal, _ := jsoniter.Marshal(param)

	req, _ := http.NewRequest("POST", url, bytes.NewReader(marshal))
	req.Header.Set("x-platform", "Server")
	req.Header.Set("Content-Type", "application/json")
	var resp *http.Response
	resp, err := httpClient.Do(req)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	body, err := GetHttpResponseBody(resp)
	if err != nil {
		return err
	}

	jsoniter.Unmarshal([]byte(body), &respData)

	for _, language := range languages {
		if _, ok := respData.Data[language]; !ok {
			continue
		}

		target := language
		if language == "en-US" {
			target = "en"
			if _, ok := codes.StatusText[target]; !ok {
				codes.StatusText[target] = make(map[string]string)
			}
			for key, value := range respData.Data[language] {
				codes.StatusText[target][key] = value
			}

			target = language
		}

		if _, ok := codes.StatusText[target]; !ok {
			codes.StatusText[target] = make(map[string]string)
		}
		for key, value := range respData.Data[language] {
			codes.StatusText[target][key] = value
		}
	}

	return nil
}

func GetHttpResponseBody(resp *http.Response) (string, error) {
	if resp == nil || resp.Body == nil {
		return "", errors.New("resp is empty")
	}

	bodyData, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	if resp.StatusCode != 200 {
		return "", errors.New(fmt.Sprintf("HttpStatusCode: %d", resp.StatusCode))
	}

	_ = resp.Body.Close()
	return string(bodyData), nil
}

func (d *BasicData) fatalError(err error) {
	if err != nil {
		log.Fatal(err.Error())
	}
}

func (d *BasicData) backgroundRun(interval time.Duration, duration time.Duration, f func(time.Duration) error) {
	go func() {
		time.Sleep(time.Duration(rand.Int63n(int64(interval))))
		for {
			if err := f(duration); err != nil {
				log.Error("sync failed", log.Errval(err))
			}
			time.Sleep(interval)
		}
	}()
	return
}
